﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using SimpleOrmCFPC.Apis.Db;
using SimpleOrmCFPC.Core.Model;
using SimpleOrmCFPC.Core.Query.OrderBys;
using SimpleOrmCFPC.Core.Query.Requests;
using SimpleOrmCFPC.Core.Query.Select;
using SimpleOrmCFPC.Core.Query.Where;
using SimpleOrmCFPC.Core.Query.expressions;
using SimpleOrmCFPC.Core.Query.expressions.ExprssionCompilers;
using SimpleOrmCFPC.Core.Query.expressions.ExprssionCompilers.Helpers;
using SimpleOrmCFPC.Core.Query.expressions.RequestBuilder.WhereElmentsBuilder;
using SimpleOrmCFPC.Core.Query.expressions.RequestBuilder.WhereElmentsBuilder.Helpers;

namespace SimpleOrmCFPC.Core.Query
{
   public static class SQLLinqFactory
    {
        public static SQLLinq<T> Create<T>(IDb executor_P)
            where T : new()
        {
           var expressionCompiler = CreateExpressionCompiler();
           return new SQLLinq<T>(new OrderByComputer(), new RequestExecutor(executor_P), new SelectComputer(), new SQLRequest(null, null, new List<Ordering>(), new List<IWhereElement>(), new List<string>() { typeof(T).GetEntityName() }, new List<string>()), expressionCompiler);
        }

        public static AnyWhereElementFromExpressionComputer CreateExpressionCompiler()
        {
            var whereElementBuilder = new AnyWhereElementFromExpressionComputer();
            var constantWhereElementBuilder = new ConstantWhereElementBuilder();
            var cast = new CastWhereElementFromExpressionComputer(whereElementBuilder);
            whereElementBuilder.Add(expr => expr is BinaryExpression, new BinaryExpressionWhereElementBuilder(whereElementBuilder));
            whereElementBuilder.Add(expr => expr.NodeType == ExpressionType.Constant, constantWhereElementBuilder);
            whereElementBuilder.Add(expr => expr.NodeType == ExpressionType.Convert, cast);
            whereElementBuilder.Add(expr => expr.NodeType == ExpressionType.Call, new FromMethodCallCompileResultFactory(whereElementBuilder));
            whereElementBuilder.Add(expr => expr.NodeType == ExpressionType.MemberAccess, new MemberWhereElementBuilder());
            return whereElementBuilder;
        }
    }
}